home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 November: Tool Chest / Dev.CD Nov 00 TC Disk 1.toast / Sample Code / Contributed / SpriteWorld / SpriteWorld Files / BlitPixie / Sources / BlitPixieRLECompiler.c < prev    next >
Encoding:
Text File  |  2000-10-06  |  10.4 KB  |  393 lines  |  [TEXT/CWIE]

  1. ///--------------------------------------------------------------------------------------
  2. //    BlitPixieRLECollision
  3. //
  4. //        based on original code by Mick Foley <mick@emf.net>
  5. //        from the book "Tricks of the Mac Game Programming Gurus" by Hayden Books.
  6. //
  7. //    Written by Anders F Björklund <afb@algonet.se>
  8. //    © 1998-99 afb.
  9. ///--------------------------------------------------------------------------------------
  10.  
  11. #ifndef GENERATINGASM // do not include for asm file generation
  12.  
  13. #ifdef macintosh
  14.  
  15. #include <Types.h>
  16. #include <Errors.h>
  17. #include <Memory.h>
  18.  
  19. #else
  20.  
  21. #include <stdlib.h>
  22.  
  23. #endif
  24.  
  25. #ifndef __BLITPIXIE__
  26. #include "BlitPixieHeader.h"
  27. #endif
  28.  
  29.     // Number of bytes before starting a fill run
  30. #define kMinimumFillRun                32
  31.  
  32.     // flags for compiler pixelrun state
  33. enum RunFlags
  34. {
  35.     kRunNone = 0,
  36.     kRunSkip,
  37.     kRunDraw,
  38.     kRunFill
  39. };
  40.  
  41. #define ALIGN_PTR(p)                ( (-((long) p)) & 3)
  42.  
  43. #ifdef macintosh
  44.  
  45. #define RESULT_TYPE        OSErr
  46. #define ALLOC            NewHandle
  47. #define TEMP_TYPE        Handle
  48. #define RETURN_TYPE        TokenDataHdl
  49.  
  50. #else
  51.  
  52. #define RESULT_TYPE        int
  53. #define ALLOC            malloc
  54. #define TEMP_TYPE        void*
  55. #define RETURN_TYPE        TokenDataPtr
  56.  
  57. #define noErr            0
  58. #define paramErr        -50
  59. #define memFullErr        -28
  60.  
  61. #endif
  62.  
  63. ///--------------------------------------------------------------------------------------
  64. //        RLEParsePixels - create RLE tokens 
  65. ///--------------------------------------------------------------------------------------
  66.  
  67. RESULT_TYPE BlitPixieRLEParsePixels(
  68.     unsigned char *srcStartAddrP,
  69.     unsigned char *maskStartAddrP,
  70.     unsigned long rowBytes,
  71.     unsigned short numBytesPerRow,
  72.     unsigned short numberOfScanLines,
  73.     unsigned short depth,
  74.     RETURN_TYPE* newPixCode)
  75. {
  76.     RESULT_TYPE     err = noErr;
  77.     unsigned long    newSize;
  78.     TEMP_TYPE        tempPixCodeH;
  79.  
  80.     unsigned char    runFlag;        
  81.  
  82.     unsigned char    *lineStartPtr;            // where is the token for the start of the current line
  83.     unsigned char     *runTokenPtr;            // where is the token for the current run
  84.     unsigned char    *dataPtr;                // points to where we are saving/encoding the data
  85.  
  86.     unsigned char    *sourcePtr;                // points to the graphics data we are saving in our image
  87.     unsigned char    *maskPtr;                // points to whichever mask we are currently encoding
  88.     unsigned char    *sourceStartPtr;        // points to the beginning of a source row.
  89.     unsigned char    *maskStartPtr;            // points to the beginning of a source row.
  90.  
  91.     unsigned long    xCounter;                // a counter to scan the shape horizontally
  92.     unsigned long    yCounter;                // a counter to scan the shape vertically
  93.  
  94.     unsigned long    thisPixel;
  95.     unsigned long    maskPixel;
  96.     unsigned long    lastPixel;
  97.     unsigned long    advance;                
  98.     
  99.     unsigned long    runCounter;                // how long is the current run? 
  100.     unsigned long    sameCounter;            // how many similar pixels in a row ?    
  101.     
  102.     Boolean            useDrawSpans = BLITPIXIE_USE_DRAW_SPANS;
  103.         
  104.     *newPixCode = NULL;
  105.     
  106.     if ( depth != 8 && depth != 16 && depth != 32 )
  107.         return paramErr;
  108.     if ( numBytesPerRow <= 0 || numberOfScanLines <= 0 )
  109.         return paramErr;
  110.     
  111.     newSize = 2 * sizeof(TokenDataType) * ( (long) numberOfScanLines * (long) numBytesPerRow) +
  112.          sizeof(TokenDataType) * numberOfScanLines + sizeof(TokenDataType);
  113.  
  114.     advance = depth >> 3;
  115.         
  116.     tempPixCodeH = ALLOC(newSize);
  117.     if (tempPixCodeH != NULL)
  118.     {
  119.     
  120.     #if macintosh
  121.     
  122.         // lock the handle and get the pointer
  123.         HLock ((Handle) tempPixCodeH);
  124.         dataPtr = (unsigned char *) ( *tempPixCodeH );
  125.     
  126.     #else
  127.         // just get the pointer
  128.         dataPtr = (unsigned char *) ( tempPixCodeH );
  129.     
  130.     #endif
  131.         
  132.         sourceStartPtr = ( unsigned char * ) srcStartAddrP;
  133.         maskStartPtr = ( unsigned char * ) maskStartAddrP;
  134.         
  135.         // scan the shape row by row
  136.         for( yCounter = 0; yCounter < numberOfScanLines; yCounter++ )
  137.         {
  138.             // we need to store where this line starts so we can fill in the lineStart token later.
  139.             lineStartPtr = dataPtr;
  140.             dataPtr += sizeof( TokenDataType );
  141.                 
  142.             // at the beginning of each row we are not in any run
  143.             runFlag = kRunNone;
  144.             runCounter = 0;
  145.             sameCounter = 0;
  146.             
  147.             // move to the start of the row
  148.             sourcePtr = sourceStartPtr;
  149.             maskPtr = maskStartPtr;
  150.             
  151.             // scan each pixel of this row
  152.             for( xCounter = 0; xCounter < numBytesPerRow; xCounter += advance)
  153.             {
  154.                 // check the mask to see if this is a clear pixel or not.
  155.                 switch ( depth )
  156.                 {
  157.                     case 8:        maskPixel = *((unsigned char  *) maskPtr);    break;
  158.                     case 16:    maskPixel = *((unsigned short *) maskPtr);    break;
  159.                     case 32:    maskPixel = *((unsigned long  *) maskPtr);    break;
  160.                 }
  161.                 
  162.                 if ( maskPixel != 0)
  163.                 {    // pixel is transparent
  164.             
  165.                     sameCounter = 0;
  166.                     
  167.                     switch ( runFlag )
  168.                     {
  169.                         case kRunSkip:
  170.                                 // continue skip run
  171.                             runCounter += advance;
  172.                             break;
  173.                         case kRunDraw:
  174.                                 // end draw run
  175.                             *((TokenDataType *) runTokenPtr) = ( kDrawPixelsToken << kTokenShift ) + runCounter;
  176.                             dataPtr += ALIGN_PTR(dataPtr);
  177.                             
  178.                                 // start skip run
  179.                             runTokenPtr = dataPtr;
  180.                             dataPtr += sizeof(TokenDataType);
  181.                             runFlag = kRunSkip;
  182.                             runCounter = advance;
  183.                             
  184.                             break;
  185.                         case kRunFill:
  186.                                 // end fill run
  187.                             *((TokenDataType *) runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
  188.                             runTokenPtr += sizeof(TokenDataType);
  189.                             if ( depth < 16 )    lastPixel |= lastPixel << 8;
  190.                             if ( depth < 32 )    lastPixel |= lastPixel << 16;
  191.                             *( ( unsigned long * )runTokenPtr ) = lastPixel;
  192.                             runTokenPtr += sizeof(unsigned long);
  193.                             
  194.                                 // start skip run
  195.                             runTokenPtr = dataPtr;
  196.                             dataPtr += sizeof(TokenDataType);
  197.                             runFlag = kRunSkip;
  198.                             runCounter = advance;
  199.                             break;
  200.                         case kRunNone:
  201.                                 // start skip run
  202.                             runTokenPtr = dataPtr;
  203.                             dataPtr += sizeof(TokenDataType);
  204.                             runFlag = kRunSkip;
  205.                             runCounter = advance;
  206.                             break;
  207.                     }
  208.                 }
  209.                 else    // pixel is masked
  210.                 {
  211.                     switch ( depth )
  212.                     {
  213.                         case 8:        thisPixel = *((unsigned char  *) sourcePtr);    break;
  214.                         case 16:    thisPixel = *((unsigned short *) sourcePtr);    break;
  215.                         case 32:    thisPixel = *((unsigned long  *) sourcePtr);    break;
  216.                     }
  217.                     
  218.                     if ( useDrawSpans && (thisPixel == lastPixel) && (sameCounter + advance >= kMinimumFillRun) )
  219.                     {
  220.                         switch (runFlag)
  221.                         {
  222.                             case kRunFill:
  223.                                     // continue fill run
  224.                                 runCounter += advance;
  225.                                 break;
  226.                             case kRunDraw:
  227.                                 if ( runCounter > sameCounter )
  228.                                 {
  229.                                         // end draw run
  230.                                     *((TokenDataType *) runTokenPtr) =
  231.                                         ( kDrawPixelsToken << kTokenShift ) + (runCounter - sameCounter);
  232.                                     
  233.                                     dataPtr -= sameCounter;
  234.                                     dataPtr += ALIGN_PTR(dataPtr);
  235.                                 }
  236.                                 else
  237.                                 {
  238.                                         // delete draw run
  239.                                     dataPtr = runTokenPtr;
  240.                                 }
  241.                                 
  242.                                     // start fill run
  243.                                 runTokenPtr = dataPtr;
  244.                                 dataPtr += sizeof(TokenDataType) + sizeof(unsigned long);
  245.                                 runFlag = kRunFill;
  246.                                 runCounter = sameCounter + advance;
  247.                                 break;
  248.                         }
  249.                     }
  250.                     else
  251.                     {
  252.                         if ( sameCounter > 0 && thisPixel == lastPixel )
  253.                             sameCounter += advance;
  254.                         else
  255.                             sameCounter = advance;
  256.                         
  257.                         switch ( runFlag )
  258.                         {
  259.                             case kRunDraw:
  260.                                     // continue draw run
  261.                                 runCounter += advance;
  262.                                 break;
  263.                             case kRunFill:
  264.                                     // end fill run
  265.                                 *((TokenDataType *) runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
  266.                                 runTokenPtr += sizeof(TokenDataType);
  267.                             
  268.                                 if ( depth < 16 )    lastPixel |= lastPixel << 8;
  269.                                 if ( depth < 32 )    lastPixel |= lastPixel << 16;
  270.                                 *( ( unsigned long * )runTokenPtr ) = lastPixel;
  271.                                 runTokenPtr += sizeof(unsigned long);
  272.                             
  273.                                     // start draw run
  274.                                 runTokenPtr = dataPtr;
  275.                                 dataPtr += sizeof(TokenDataType);
  276.                                 runFlag = kRunDraw;
  277.                                 runCounter = advance;
  278.                                 break;
  279.                         case kRunSkip:
  280.                                     // end skip run
  281.                                 *((TokenDataType *) runTokenPtr) = ( kSkipPixelsToken << kTokenShift ) + runCounter;
  282.                                 
  283.                                     // start draw run
  284.                                 runTokenPtr = dataPtr;
  285.                                 dataPtr += sizeof(TokenDataType);
  286.                                 runFlag = kRunDraw;
  287.                                 runCounter = advance;
  288.                                 break;
  289.                         case kRunNone:
  290.                                     // start draw run
  291.                                 runTokenPtr = dataPtr;
  292.                                 dataPtr += sizeof(TokenDataType);
  293.                                 runFlag = kRunDraw;
  294.                                 runCounter = advance;
  295.                                 break;
  296.                         }
  297.                         
  298.                         // copy the pixel
  299.                         switch ( depth )
  300.                         {
  301.                             case 8:        *((unsigned char  *) dataPtr) = thisPixel;    dataPtr += 1; break;
  302.                             case 16:    *((unsigned short *) dataPtr) = thisPixel;    dataPtr += 2; break;
  303.                             case 32:    *((unsigned long  *) dataPtr) = thisPixel;    dataPtr += 4; break;
  304.                         }
  305.                         
  306.                         lastPixel = thisPixel;
  307.                     }
  308.                 }
  309.                                         
  310.                 // move to the next pixel
  311.                 sourcePtr += advance;
  312.                 maskPtr += advance;
  313.             }
  314.             
  315.                 // if we're finishing up a draw/fill run, we need to write out the final data.    
  316.             switch ( runFlag )
  317.             {
  318.                 case kRunSkip:
  319.                     // delete the skip run
  320.                     dataPtr = runTokenPtr;
  321.                     break;
  322.                 case kRunDraw:
  323.                     // create the draw token
  324.                     *( (TokenDataType *) runTokenPtr ) = ( kDrawPixelsToken << kTokenShift ) + runCounter;
  325.                     dataPtr += ALIGN_PTR(dataPtr);
  326.                     break;
  327.                 case kRunFill:
  328.                     // create the fill token
  329.                     *( ( TokenDataType *)runTokenPtr) = ( kSingleColorToken << kTokenShift ) + runCounter;
  330.                     runTokenPtr += sizeof(TokenDataType);
  331.                     
  332.                     if ( depth < 16 )    lastPixel |= lastPixel << 8;
  333.                     if ( depth < 32 )    lastPixel |= lastPixel << 16;
  334.                     *( ( unsigned long *) runTokenPtr) = lastPixel;
  335.                     runTokenPtr += sizeof(unsigned long);
  336.                     break;
  337.             }
  338.                 
  339.             // create the line start token
  340.             *( ( TokenDataType * )lineStartPtr ) = ( kLineStartToken << kTokenShift ) +
  341.                                 ( (long) dataPtr - sizeof(TokenDataType) - (long) lineStartPtr);
  342.                 
  343.             // move the row start to the next row
  344.             sourceStartPtr += rowBytes;
  345.             maskStartPtr += rowBytes;
  346.         }
  347.  
  348.         // create the end of shape token
  349.         *( ( TokenDataType * )dataPtr ) = kEndShapeToken << kTokenShift;
  350.         dataPtr += sizeof(TokenDataType);
  351.                         
  352.     #ifdef macintosh
  353.     
  354.         newSize = dataPtr - (unsigned char *) (*tempPixCodeH );
  355.     
  356.             // Unlock the handle
  357.         HUnlock( (Handle) tempPixCodeH );
  358.         
  359.             // Resize the handle to match the real size of the shape
  360.         SetHandleSize( (Handle) tempPixCodeH, newSize );
  361.         err = MemError();
  362.     
  363.     #else
  364.     
  365.         newSize = dataPtr - (unsigned char *) (tempPixCodeH);
  366.     
  367.         tempPixCodeH = realloc( tempPixCodeH, newSize );
  368.         if ( tempPixCodeH == NULL )
  369.             err = memFullErr;
  370.             
  371.     #endif
  372.         
  373.         if (err == noErr)
  374.         {
  375.             *newPixCode = (RETURN_TYPE) tempPixCodeH;
  376.         }
  377.     }
  378.     else
  379.     {
  380.         err = memFullErr;
  381.     }
  382.  
  383.     return err;
  384. }
  385.  
  386. #endif //GENERATINGASM
  387.  
  388.  
  389.  
  390.  
  391.  
  392.  
  393.